﻿<h1>Value Conversion, Assignment and Comparison Rules in Go</h1>

<p>
This article will list all the value comparison,
conversion and comparison rules in Go.
</p>

<a class="anchor" id="conversion"></a>
<h3>Value Conversion Rules</h3>

<!--
<p>
Note, the definition of conversion in Go 101 is not exactly the same as Go specification.
The conversion in Go spec means explicit conversion.
The conversions in Go 101 include both explicit and implicit conversions.
</p>
-->

<p>
In Go, if a value <code>v</code> can be explicitly converted to type <code>T</code>,
the conversion can be represented as the form <code>(T)(v)</code>.
For most cases, in particular <code>T</code> is a type name (an identifier),
the form can be simplified to <code>T(v)</code>.
</p>

<p>
One fact we should know is,
when it says a value <code>x</code> can be implicitly converted to a type <code>T</code>,
then it means <code>x</code> can also be explicitly converted to type <code>T</code>.
</p>

<h4>1. the apparent conversion rule</h4>

<div class="well">
If two types denote the identical type,
then their values can be <b>implicitly</b> converted to either type of the two.
</div>

<div>
For example,
<ul>
<li>
	values of type <code>byte</code> and <code>uint8</code> can be converted to each other.
</li>
<li>
	values of type <code>rune</code> and <code>int32</code> can be converted to each other.
</li>
<li>
	values of type <code>[]byte</code> and <code>[]uint8</code> can be converted to each other.
</li>
</ul>
</div>

<p>
Nothing more to explain about this rule, whether you think this case involves conversions or not.
</p>

<a class="anchor" id="conversion-rule-underlying-types"></a>
<h4>2. underlying type related conversion rules</h4>

<div class="well">
Given a non-interface value <code>x</code> and a non-interface type <code>T</code>, assume the type of <code>x</code> is <code>Tx</code>,
<ul>
<li>
	if <code>Tx</code> and <code>T</code> share the same <a href="type-system-overview.html#underlying-type">underlying type</a> (ignoring struct tags),
	then <code>x</code> can be explicitly converted to <code>T</code>.
</li>
<li>
	if either <code>Tx</code> or <code>T</code> is a <a href="type-system-overview.html#non-defined-type">non-defined type</a>
	and their underlying types are identical (considering struct tags),
	then <code>x</code> can be <b>implicitly</b> converted to <code>T</code>.
</li>
<li>
	if <code>Tx</code> and <code>T</code> have different underlying types,
	but both <code>Tx</code> and <code>T</code> are non-defined pointer types
	and their base types share the same underlying type (ignoring struct tags),
	then <code>x</code> can (and must) be explicitly converted to <code>T</code>.
</li>
</ul>
</div>

<p><i>
(Note, the two <b>ignoring struct tags</b> occurrences have taken effect since Go 1.8.)
</i></p>

<div>
An example:
<pre class="line-numbers"><code class="language-go">package main

func main() {
	// []int, IntSlice and MySlice share
	// the same underlying type: []int
	type IntSlice []int
	type MySlice  []int

	var s  = []int{}
	var is = IntSlice{}
	var ms = MySlice{}
	var x struct{n int `foo`}
	var y struct{n int `bar`}

	// The two implicit conversions both doesn't work.
	/*
	is = ms // error
	ms = is // error
	*/

	// Must use explicit conversions here.
	is = IntSlice(ms)
	ms = MySlice(is)
	x = struct{n int `foo`}(y)
	y = struct{n int `bar`}(x)

	// Implicit conversions are okay here.
	s = is
	is = s
	s = ms
	ms = s
}
</code></pre>

<p>
</p>

Pointer related conversion example:
<pre class="line-numbers"><code class="language-go">package main

func main() {
	type MyInt int
	type IntPtr *int
	type MyIntPtr *MyInt

	var pi = new(int)  // the type of pi is *int
	// ip and pi have the same underlying type,
	// and the type of pi is non-defined, so
	// the implicit conversion works.
	var ip IntPtr = pi

	// var _ *MyInt = pi // can't convert implicitly
	var _ = (*MyInt)(pi) // ok, must explicitly

	// Values of *int can't be converted to MyIntPtr
	// directly, but can indirectly.
	/*
	var _ MyIntPtr = pi  // can't convert implicitly
	var _ = MyIntPtr(pi) // can't convert explicitly
	*/
	var _ MyIntPtr = (*MyInt)(pi)  // ok
	var _ = MyIntPtr((*MyInt)(pi)) // ok

	// Values of IntPtr can't be converted to
	// MyIntPtr directly, but can indirectly.
	/*
	var _ MyIntPtr = ip  // can't convert implicitly
	var _ = MyIntPtr(ip) // can't convert explicitly
	*/
	var _ MyIntPtr = (*MyInt)((*int)(ip))  // ok
	var _ = MyIntPtr((*MyInt)((*int)(ip))) // ok
}
</code></pre>
</div>

<h4>3. channel specific conversion rule</h4>

<div class="well">
	Assume <code>Tx</code> is a bidirectional channel type, <code>T</code> is also a channel type (bidirectional or not),
	if <code>Tx</code> and <code>T</code> have the identical element type,
	and either <code>Tx</code> or <code>T</code> is a non-defined type,
	then <code>x</code> can be <b>implicitly</b> converted to <code>T</code>.
</div>

<!--
a potentail bug: https://github.com/golang/go/issues/29469
-->

<div>
Example:
<pre class="line-numbers"><code class="language-go">package main

func main() {
	type C chan string
	type C1 chan<- string
	type C2 <-chan string

	var ca C
	var cb chan string

	cb = ca // ok, same underlying type
	ca = cb // ok, same underlying type

	// The 4 lines compile okay for this 2nd rule.
	var _, _ chan<- string = ca, cb // ok
	var _, _ <-chan string = ca, cb // ok
	var _ C1 = cb                   // ok
	var _ C2 = cb                   // ok

	// Values of C can't be converted
	// to C1 and C2 directly.
	/*
	var _ = C1(ca) // compile error
	var _ = C2(ca) // compile error
	*/

	// Values of C can be converted
	// to C1 and C2 indirectly.
	var _ = C1((chan<- string)(ca)) // ok
	var _ = C2((<-chan string)(ca)) // ok
	var _ C1 = (chan<- string)(ca)  // ok
	var _ C2 = (<-chan string)(ca)  // ok
}
</code></pre>
</div>

<a class="anchor" id="conversion-rule-implementation"></a>
<h4>4. interface implementation related conversion rules</h4>

<div class="well">
Given a value <code>x</code> and an interface type <code>I</code>,
if the type (or the default type) of <code>x</code> is <code>Tx</code>
and <code>Tx</code> implements <code>I</code>,
then <code>x</code> can be <b>implicitly</b> converted to type <code>I</code>.
The conversion result is an interface value (of type <code>I</code>),
which boxes
<ul>
<li>a copy of <code>x</code>, if <code>Tx</code> is a non-interface type;</li>
<li>a copy of the dynamic value of <code>x</code>, if <code>Tx</code> is an interface type.</li>
</ul>
</div>

<!--
<div>
Example:
<pre class="line-numbers"><code class="language-go">package main

type Filter interface {
	Filte(n int) bool
}

type MultipleFilter struct {
	Divisor int
}

func (mf MultipleFilter) Filte(n int) bool {
	return n % mf.Divisor == 0
}

func main() {
	var mf = MultipleFilter{11}
	// mf's type MultipleFilter implements Filter,
	// so here the implicit conversion is okay.
	var filter = mf

	// All types implement interface{} type, so any
	// value can be converted to interface{} implicitly.

	var n int = 123
	var b bool = true
	var s string = "abc"

	var _ interface{} = n
	var _ interface{} = b
	var _ interface{} = s
	var _ interface{} = mf

	// interface type Filter also implements interface{}
	var _ interface{} = filter
}
</code></pre>
<p>
</p>
</div>

<a class="anchor" id="conversion-rule-type-assertion"></a>
<h4>4. type assertion conversion rules</h4>
-->

<div class="well">
Given an interface value <code>x</code> with its dynamic type as <code>T</code>,
<code>x</code> can be safely converted to type <code>T</code> through
the type assertion syntax <code>x.(T)</code>.
</div>

<div class="well">
Given an interface value <code>x</code> and an interface type <code>I</code>,
if the dynamic type of <code>x</code> implements <code>I</code>,
then <code>x</code> can be safely converted to <code>I</code>
through the type assertion syntax <code>x.(I)</code>.
</div>

<!--
<div>
An example:
<pre class="line-numbers"><code class="language-go">package main

type I interface {
	f()
}

type T string
func (T) f(){}

func main() {
	var it interface{} = T("abc")
	var is interface{} = "abc"

	// The two are both okay, for T
	// implements both I and interface{}.
	var _ T = it.(T)
	var _ I = it.(I)

	// This one is also okay, for built-in
	// type string implements interface{}.
	var _ string = is.(string)

	// The following 3 lines all compile okay
	// but all will panic at run time.
	// _ = is.(I)
	// _ = is.(T)
	// _ = it.(string)
}
</code></pre>
</div>
-->

<p>
Please read <a href="interface.html">interfaces in Go</a> for details and examples.
</p>

<h4>5. untyped value conversion rule</h4>

<div class="well">
An untyped value can be <b>implicitly</b> converted to type <code>T</code>,
if the untyped value can represent as values of type <code>T</code>.
</div>

<div>
Example:
<pre class="line-numbers"><code class="language-go">package main

func main() {
	var _ []int = nil
	var _ map[string]int = nil
	var _ chan string = nil
	var _ func()() = nil
	var _ *bool = nil
	var _ interface{} = nil

	var _ int = 123.0
	var _ float64 = 123
	var _ int32 = 1.23e2
	var _ int8 = 1 + 0i
}
</code></pre>
</div>

<h4>6. constants conversion rule</h4>

<p><i>
(This rule is some overlapped with the last one.)
</i></p>

<p>
Generally, converting a constant still yields a constant as result.
(Except converting a constant string to byte slice or rune slice
described in the below 8th rules.)
</p>

<div class="well">
Given a constant value <code>x</code> and a type <code>T</code>, if <code>x</code> is representable as a value of type <code>T</code>,
then <code>x</code> can be explicitly converted to <code>T</code>. In particular if <code>x</code> is an untyped value,
then <code>x</code> can be <b>implicitly</b> converted to <code>T</code>.
</div>

<!--
<p>
Note, in case of <code>x</code> is a floating-point constant and <code>T</code> is a floating-point type,
the conversion result <code>T(x)</code> is the rounded value of <code>x</code> by using IEEE 754 round-to-even rules,
but with an IEEE <code>-0.0</code> further rounded to an unsigned <code>0.0</code>.
</p>
-->

<div>
Example:
<pre class="line-numbers"><code class="language-go">package main

func main() {
	const I = 123
	const I1, I2 int8 = 0x7F, -0x80
	const I3, I4 int8 = I, 0.0

	const F = 0.123456789
	const F32 float32 = F
	const F32b float32 = I
	const F64 float64 = F
	const F64b = float64(I3) // must be explicit

	const C1, C2 complex64 = F, I
	const I5 = int(C2) // must be explicit
}
</code></pre>
</div>

<h4>7. non-constant number conversion rules</h4>

<div class="well">
Non-constant floating-point and integer values can be explicitly
converted to any floating-point and integer types.
</div>

<div class="well">
Non-constant complex values can be explicitly converted to any complex types.
</div>

<div>
Note,
<ul>
<li>Complex non-constant values can't be converted to floating-point and integer types.</li>
<li>Floating-point and integer non-constant values can't be converted to complex types.</li>
<li>Data overflow and rounding are allowed in non-constant number conversions.
	When converting a floating-point non-constant number to an integer, the fraction is discarded (truncation towards zero).
</li>
</ul>

An example:
<pre class="line-numbers"><code class="language-go">package main

import "fmt"

func main() {
	var a, b = 1.6, -1.6 // both are float64
	fmt.Println(int(a), int(b)) // 1 -1

	var i, j int16 = 0x7FFF, -0x8000
	fmt.Println(int8(i), uint16(j)) // -1 32768

	var c1 complex64 = 1 + 2i
	var _ = complex128(c1)
}
</code></pre>
</div>

<h4>8. string related conversion rules</h4>

<div class="well">
If the type (or default type) of a value is an integer type,
then the value can be explicitly converted to string types.
</div>

<div class="well">
A string value can be explicitly converted to a slice type
whose underlying type is <code>[]byte</code> (a.k.a., <code>[]uint8</code>),
and vice versa.
</div>

<div class="well">
A string value can be explicitly converted to a slice type
whose underlying type is <code>[]rune</code> (a.k.a., <code>[]int32</code>),
and vice versa.
</div>

<p>
Please read <a href="string.html#conversions">strings in Go</a> for details and examples.
</p>

<h4>9. unsafe pointers related conversion rules</h4>

<div class="well">
A pointer value of any type can be explicitly converted to a type whose underlying type is <code>unsafe.Pointer</code>, and vice versa.
</div>

<div class="well">
An uintptr value can be explicitly converted to a type whose underlying type is <code>unsafe.Pointer</code>, and vice versa.
</div>

<p>
Please read <a href="unsafe.html">type-unsafe pointers in Go</a> for details and examples.
</p>

<h3>Value Assignment Rules</h3>

<p>
Assignments can be viewed as implicit conversions.
Implicit conversion rules are listed among all conversion rules in the last section.
</p>

<p>
Besides these rules, the destination values in assignments must be
addressable values, map index expressions, or the blank identifier.
</p>

<!--
<div class="well">
In an assignment, if the target value is a new declared variable without given a
type in code, then the type of the new variable is
<ul>
<li>the type of the source value, if the source value is a typed value;</li>
<li>the default type of the source value, if the source value is an untyped constant.</li>
</ul>
</div>

<p>
</p>
-->

<p>
In an assignment, the source value is copied to the destination value.
Precisely speaking, the <a href="value-part.html">direct part</a>
of the source value is copied to the destination value.
</p>

<p>
Note, parameter passing and result returning are both value assignments actually.
</p>

<!--
<p>
For most value assignments, the <a href="value-part.html">direct part</a>
of each source value is copied to the direct part of the corresponding
destination value, except that destination value is an interface value.
</p>

<p>
In an assignment, if the destination value is an interface value but
the source value is not, then (the direct part of) the source value
will be copied and the copy result will be stored in
the destination interface value as dynamic value.
The standard compiler makes some special treatments here
if the source value is not a pointer value.
If the source value is not a pointer value,
the direct part of the source value
will be copied and a pointer to the (hidden and immutable) copy
will be stored in the destination interface value.
</p>

<p>
In an assignment,
if both the destination and source values are interface values,
then (the direct part of) the dynamic value of the source interface value
will be copied and the copy result will be stored in
the destination interface value as dynamic value.
The standard compiler makes some optimizations here so that
a pointer is always copied in the process.
</p>
-->

<a class="anchor" id="comparison-rules"></a>
<h3>Value Comparison Rules</h3>

<div>

<p>
Go specification
<a href="https://golang.org/ref/spec#Comparison_operators">states</a>:
</p>

<div class="alert alert-success">
In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.
</div>

<p>
So, the comparison rule is much like the assignment rule.
In other words, two values are comparable if one of them can be implicitly converted to the type of the other.
Right? Almost, for there is an exception for the above basic comparison rule.
</p>

<!--
https://github.com/golang/go/issues/28164#issuecomment-430733364
-->
<div class="alert alert-danger">
If one of the two operands in a comparison is an interface value,
and the other operand is a non-interface value of an
<a href="type-system-overview.html#types-not-support-comparison">incomparable type</a>
(which should implement the former operand interface type),
then the comparison is invalid, even if the non-interface value
can be implicitly converted to the interface type.
</div>

<p>
Note, although values of slice/map/function types don't support comparisons,
they can be compared with untyped nil values (a.k.a., bare <code>nil</code> identifiers).
</p>

The above described basic rules don't cover all cases.
What about if both of the two operands in a comparison are untyped (constant) values?
The additional rules are simple:
<ul>
<li>
	untyped boolean values can be compared with untyped boolean values.
</li>
<li>
	untyped numeric values can be compared with untyped numeric values.
</li>
<li>
	untyped string values can be compared with untyped string values.
</li>
</ul>

<p>
The results of comparing two untyped numeric values obey intuition.
</p>

<p>
Note, an untyped nil value can't be compared with another untyped nil value.
</p>

<p>
Any comparison results an untyped boolean value.
</p>

The following example shows some incomparable types related comparisons.

<pre class="line-numbers"><code class="language-go">package main

// Some variables of incomparable types.
var s []int
var m map[int]int
var f func()()
var t struct {x []int}
var a [5]map[int]int

func main() {
	// The following lines fail to compile.
	/*
	_ = s == s
	_ = m == m
	_ = f == f
	_ = t == t
	_ = a == a
	_ = nil == nil
	_ = s == interface{}(nil)
	_ = m == interface{}(nil)
	_ = f == interface{}(nil)
	*/

	// The following lines compile okay.
	_ = s == nil
	_ = m == nil
	_ = f == nil
	_ = 123 == interface{}(nil)
	_ = true == interface{}(nil)
	_ = "abc" == interface{}(nil)
}
</code></pre>

<p>
</p>

</div>

<a class="anchor" id="comparison-implementation"></a>
<h4>How Are Two Values Compared?</h4>

<div>
Assume two values are comparable, and they have the same type <code>T</code>.
(If they have different types, one of them must be implicitly convertible to the type of the other.
Here we don't consider the cases in which both the two values are untyped.)
<ol>
<li>
	If <code>T</code> is a boolean type,
	then the two values are equal only if they are both <code>true</code> or both <code>false</code>.
</li>
<li>
	If <code>T</code> is an integer type,
	then the two values are equal only if they have the same representation in memory.
</li>
<li>
	If <code>T</code> is a floating-point type,
	then the two values are equal only if any of the following conditions is satisfied:
	<ul>
	<li>
		they are both <code>+Inf</code>.
	</li>
	<li>
		they are both <code>-Inf</code>.
	</li>
	<li>
		each of them is either <code>-0.0</code> or <code>+0.0</code>.
	</li>
	<li>
		they are both not <code>NaN</code> and they have the same bytes representations in memory.
	</li>
	</ul>
</li>
<li>
	If <code>T</code> is a complex type,
	then the two values are equal only if their real parts (as floating-point values)
	and imaginary parts (as floating-point values) are both equal.
</li>
<li>
	If <code>T</code> is a pointer type (either safe or unsafe),
	then the two values are equal only if the memory addresses stored in them are equal.
</li>
<li>
	If <code>T</code> is a channel type, the two channel values are equal
	if they both reference the same underlying internal channel structure value
	or they are both nil channels.
</li>
<li>
	If <code>T</code> is a struct type, then
	<a href="struct.html#comparison">each pair of the corresponding
	fields of the two struct values will be compared</a>.
</li>
<li>
	If <code>T</code> is an array type, then
	<a href="container.html#comparison">each pair of the corresponding
	elements of the two array values will be compared</a>.
</li>
<li>
	If <code>T</code> is an interface type, please read
	<a href="interface.html#comparison">how two interface values are compared</a>.
</li>
<li>
	If <code>T</code> is a string type, please read
	<a href="string.html#comparison">how two string values are compared</a>.
</li>
</ol>

Please note, comparing two interfaces with the same incomparable dynamic type
produces a panic.
The following is an example in which some panics will occur in comparisons.

<pre class="line-numbers"><code class="language-go">package main

func main() {
	type T struct {
		a interface{}
		b int
	}
	var x interface{} = []int{}
	var y = T{a: x}
	var z = [3]T{}

	// Each of the following line can produce a panic.
	_ = x == x
	_ = y == y
	_ = z == z
}
</code></pre>

<p>
Please note, the two code lines involved <code>z</code> compile okay for
the <code>go build</code> and <code>go install</code> commands in any version of Go SDK,
but fail to compile for the <code>go run</code> command in Go SDK 1.9 and 1.10.
This is <a href="https://github.com/golang/go/issues/24747">a known bug</a> in the standard Go compiler 1.9 and 1.10.
</p>
</div>


